package com.bee.bootstrap.roleResource.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.bee.bootstrap.plugs.shiro.ShiroFilerChainManager;
import com.bee.bootstrap.resource.entity.Resource;
import com.bee.bootstrap.resource.service.IResourceService;
import com.bee.bootstrap.role.entity.Role;
import com.bee.bootstrap.role.service.IRoleService;
import com.bee.bootstrap.roleResource.entity.RoleResource;
import com.bee.bootstrap.roleResource.mapper.RoleResourceMapper;
import com.bee.bootstrap.roleResource.service.IRoleResourceService;
import com.bee.bootstrap.roleResource.view.UrlResourceView;
import com.bee.bootstrap.user.entity.User;
import com.bee.bootstrap.userRole.service.IUserRoleService;
import com.bee.common.core.enums.PermissionLevelEnum;
import com.bee.common.core.jsonview.DataView;
import com.bee.common.core.jsonview.DataWithView;
import com.bee.common.core.jsonview.JsonViews;
import com.bee.common.core.result.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author liekkas
 * @since 2018-05-25
 */
@Service("roleResourceService")
public class RoleResourceServiceImpl extends ServiceImpl<RoleResourceMapper, RoleResource> implements IRoleResourceService {

    @Autowired
    private IUserRoleService userRoleServiceImpl;
    @Autowired
    private IResourceService resourceServiceImpl;
    @Autowired
    private IRoleService roleServiceImpl;
    @Autowired
    private ShiroFilerChainManager shiroFilerChainManager;


    @Override
    public Set<String> findResourcePermission(Long userId) {
        List<Resource> resources=this.findResources(userId);
        Set<String> permissions=new HashSet<String>();
        if(resources.size()>0){
            resources.forEach(resource -> {
                permissions.add(resource.getPermission());
            });
        }
        return permissions;
    }

    @Override
    public List<Resource> findResources(Long userId) {
        List<Role> roles=userRoleServiceImpl.findRoles(userId);
        List<Resource> resources=new ArrayList<Resource>();
        if(roles.size()>0){
            Set<Long> resourcesIds=new HashSet<Long>();
            Set<Long> roleIds=new HashSet<Long>();
            //角色Id
            roles.forEach(role -> {
                roleIds.add(role.getId());
            });
            List<RoleResource> roleResources=this.selectList(new EntityWrapper<RoleResource>().in("role_id",roleIds));
            roleResources.forEach(roleResource->{
                resourcesIds.add(roleResource.getResourceId());
            });
            if(roleResources.size()>0)
                resources=resourceServiceImpl.selectList(new EntityWrapper<Resource>().in("id",resourcesIds));
        }
        return resources;
    }

    @Override
    public Set<String> findResourceUrl(Long userId) {
        List<Resource> resources=this.findResources(userId);
        Set<String> urls=new HashSet<String>();
        if(resources.size()>0){
            resources.forEach(resource -> {
                urls.add(resource.getUrl());
            });
        }
        return urls;
    }

    @Override
    public Result createRoleResource(RoleResource resource) {
        resource.setCreateTime(new Date());
        this.insert(resource);
        initFilterChain();
        return Result.success("保存成功");
    }

    /**
     * 查找当前用户包含该资源的所有角色的字段最高级别权限
     * 含有*:*的默认全部字段可见
     * @param resourceId
     * @param user
     * @return
     */
    @Override
    public DataView findDataView(Long resourceId,User user) {
       RoleResource condition=new RoleResource();
       condition.setResourceId(resourceId);
       List<Role> roles=userRoleServiceImpl.findRoles(user.getId());
       List<Long> roleIds=new ArrayList<>();
       roles.forEach(role -> {
           roleIds.add(role.getId());
       });
       //判断角色权限是否包含了*:*所有权限
       boolean allAccess=false;
       List<RoleResource> roleResources=this.selectList(new EntityWrapper<RoleResource>().in("role_id",roleIds));
       List<Long> resourceIds=new ArrayList<>();
       roleResources.forEach(roleResource->{
           resourceIds.add(roleResource.getResourceId());
       });
       List<Resource> resources=resourceServiceImpl.selectList(new EntityWrapper<Resource>().in("id",resourceIds));
       for(Resource resource:resources){
           if("*:*".equals(resource.getPermission())){
               allAccess=true;
               break;
           }
       }
       String defaultPermission=PermissionLevelEnum.Internal.toString();
       if(allAccess){
           defaultPermission=PermissionLevelEnum.Public.toString();
       }else{
           roleResources=this.selectList(new EntityWrapper<RoleResource>(condition).in("role_id",roleIds));
           List<String> dataViews=new ArrayList<>();
           roleResources.forEach(roleResource -> {
               dataViews.add(roleResource.getPermissionLevel());
           });

           Collections.sort(dataViews, new Comparator<String>() {
               @Override
               public int compare(String o1, String o2) {
                   return PermissionLevelEnum.getSortByCode(o1)-PermissionLevelEnum.getSortByCode(o2);
               }
           });
           defaultPermission=dataViews.size()==0?defaultPermission:dataViews.get(0);
       }

        try {
            return new DataWithView(defaultPermission);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return new DataWithView(JsonViews.Internal.class);
    }

    @Override
    public List<RoleResource> findResourcesByRoleId(long roleId) {
        RoleResource condition=new RoleResource();
        condition.setRoleId(roleId);
        return this.selectList(new EntityWrapper<RoleResource>(condition));
    }

    @Override
    public boolean deleteResourceByRoleId(long roleId) {
        return this.delete(new EntityWrapper<RoleResource>().eq("role_id",roleId));
    }

    @Override
    public Result createRoleResources(Long roleId, List<Resource> resources) {
        List<RoleResource> roleResources=new ArrayList<>();
        resources.forEach(resource->{
            RoleResource roleResource=new RoleResource();
            roleResource.setResourceId(resource.getId());
            roleResource.setRoleId(roleId);
            roleResource.setCreateTime(new Date());
            roleResource.setPermissionLevel(resource.getPermissionLevel());
            roleResources.add(roleResource);
        });
        this.insertBatch(roleResources);
        initFilterChain();
        return Result.success();
    }

    public List<RoleResource> findAll(){
        List<RoleResource> roleResources=this.selectList(new EntityWrapper<RoleResource>().orderBy("resource_id"));
        Set<Long> roleIds=new HashSet<Long>();
        Set<Long> resourceIds=new HashSet<Long>();
        if(roleResources!=null&&roleResources.size()>0){
            roleResources.forEach(roleResource->{
                roleIds.add(roleResource.getRoleId());
                resourceIds.add(roleResource.getResourceId());
            });
            List<Role> roles=roleServiceImpl.selectList(new EntityWrapper<Role>().in("id",roleIds));
            List<Resource> resources=resourceServiceImpl.selectList(new EntityWrapper<Resource>().in("id",resourceIds));
            roleResources.forEach(roleResource->{
                roles.forEach(role->{
                    if(roleResource.getRoleId().compareTo(role.getId())==0){
                        roleResource.setRole(role);
                    }
                });
                resources.forEach(resource -> {
                    if(roleResource.getResourceId().compareTo(resource.getId())==0){
                        roleResource.setResource(resource);
                    }
                });
            });
        }
        return roleResources;
    }

    public List<UrlResourceView> summaryByResources(List<RoleResource> resources){
        String url="";
        UrlResourceView urlResourceView=null;
        List<UrlResourceView> urlResourceViews=new ArrayList<>();
        for(int i=0;i<resources.size();i++){
            RoleResource resource=resources.get(i);
            if(resource.getResource()!=null){
                if(!url.equals(resource.getResource().getUrl())){
                    //保存上一次summary的数据
                    if(urlResourceView!=null){
                        urlResourceViews.add(urlResourceView);
                    }
                    urlResourceView=new UrlResourceView();
                    urlResourceView.setUrl(resource.getResource().getUrl());
                    urlResourceView.setRoles(resource.getRole().getCode());
                    urlResourceView.setPermissions(resource.getResource().getPermission());
                    url=resource.getResource().getUrl();
                }else{
                    if(urlResourceView.getRoles().indexOf(resource.getRole().getCode())<0){
                        urlResourceView.setRoles(urlResourceView.getRoles()+","+resource.getRole().getCode());
                    }
                    if(urlResourceView.getPermissions().indexOf(resource.getResource().getPermission())<0){
                        urlResourceView.setPermissions(urlResourceView.getPermissions()+","+resource.getResource().getPermission());
                    }
                }
            }
            if(i==resources.size()-1){
                urlResourceViews.add(urlResourceView);
            }
        }
        return urlResourceViews;
    }

    @PostConstruct
    public void initFilterChain() {
        shiroFilerChainManager.initFilterChains(summaryByResources(findAll()));
    }


}
